
class Container {
    static of(value) {
        return new Container(value);
    }

    constructor(value) {
        this._value = value;
    }

    map(fn) {
        return Container.of(fn(this._value))
    }
}

class Maybe {
    static of(x) {
        return new Maybe(x)
    }

    isNothing() {
        return this._value === null || this._value === undefined;
    }

    constructor(x) {
        this._value = x;
    }

    map(fn) {
        return this.isNothing() ? this : Maybe.of(fn(this._value))
    }
}
const fp = require('lodash/fp');

//练习1
let maybe = Maybe.of([5, 6, 1]);
let ex1 = y => maybe.map((x) => fp.map((v) => fp.add(v, y), x))
console.log("1");
console.log(ex1(1));
console.log(ex1(4));

//练习2
let xs = Container.of(['do', 'ray', 'me', 'fa', 'so', 'la', 'ti', 'do']);
let ex2 = () => xs.map(fp.first)
console.log("2");
console.log(ex2());

//练习3
let safeProp = fp.curry(function(x, o) {
    return Maybe.of(o[x])
});
let user = {
    id: 2,
    name: "Albert"
};
let ex3 = () => safeProp("name", user).map(fp.first);
console.log("3");
console.log(ex3());

//练习4
let ex4 = n => Maybe.of(n).map(parseInt)
console.log("4");
console.log(ex4(4));
console.log(ex4(null));
console.log(ex4(undefined));
console.log(ex4(4.5));